import os
import time

import pygame
import sys
import random
import csv

pygame.init()
pygame.display.set_caption("贪吃蛇")
icon = pygame.image.load("./Image/snake.ico")
pygame.display.set_icon(icon)

# 创建常量
W = 600  # 与GRID_SIZE成倍数关系
H = 400
FPS = 30
GRID_SIZE = 20
LINE_SIZE = 2
SCREEN = pygame.display.set_mode((W, H));
CLOCK = pygame.time.Clock()
MENU_TEXT = ["开始游戏", "分数榜", "退出"]
SNAKE_START_POS = (W // 2, H // 2)

# 一些颜色控制啊
LINE_COLOR = (20,20,20)
FONT_COLOR = (200, 200, 200)
HIGHT_COLOR = (240, 240, 240)

# 字体载入啊
FONT_TITLE = pygame.font.Font("./Font/方正粗黑宋简体.ttf", 100)
FONT_MENU = pygame.font.Font("./Font/方正粗黑宋简体.ttf", 40)
FONT_SMALL = pygame.font.Font("./Font/方正粗黑宋简体.ttf", 20)

# 全局变量
menu_pos = []
snake_body = [[SNAKE_START_POS[0], SNAKE_START_POS[1]]]
score = 0

#载入相关图片静态资源
copyrightImage = pygame.image.load("./Image/a005.png")


# 食物的位置
food_pos_x = random.randint(0, W // GRID_SIZE-1) * GRID_SIZE
foot_pos_y = random.randint(0, H // GRID_SIZE-1) * GRID_SIZE
food_pos = [food_pos_x,foot_pos_y]

# 蛇的移动方向
move_left = False
move_right = True
move_up = False
move_down = False


# 背景格子绘制
def draw_background_grid():
    SCREEN.fill((0, 0, 0))
    for i in range(0, W, GRID_SIZE):
        pygame.draw.line(SCREEN, LINE_COLOR, (i, 0), (i, H), LINE_SIZE)
    for i in range(0, H, GRID_SIZE):
        pygame.draw.line(SCREEN, LINE_COLOR, (0, i), (W, i), LINE_SIZE)

# 菜单绘制
def draw_menu(mouse_pos):
    SCREEN.fill((0, 0, 0))

    # 绘制版权图片
    SCREEN.blit(copyrightImage, (0, H - 50))

    title = FONT_TITLE.render("贪吃蛇", True, FONT_COLOR)
    title_rect = title.get_rect(center=(W / 2, H / 2 - 100))
    SCREEN.blit(title, title_rect)

    menu_pos.clear()
    for i in range(len(MENU_TEXT)):
        begin_text = FONT_MENU.render(MENU_TEXT[i], True, FONT_COLOR)
        begin_text_rect = begin_text.get_rect(center=(W / 2, H / 2 + (i * 50)))
        menu_pos.append(begin_text_rect)
        if begin_text_rect.collidepoint(*mouse_pos):
            begin_text = FONT_MENU.render(MENU_TEXT[i], True, HIGHT_COLOR)
        else:
            begin_text = FONT_MENU.render(MENU_TEXT[i], True, FONT_COLOR)
        SCREEN.blit(begin_text, begin_text_rect)

# 绘制结束界面
def draw_end():
    # 绘制背景
    SCREEN.fill((0, 0, 0))

    # 绘制分数
    score_text = FONT_MENU.render("分数：" + str(score), True, FONT_COLOR)
    score_text_rect = score_text.get_rect(center=(W / 2, H / 2))
    SCREEN.blit(score_text, score_text_rect)

    # 绘制重新开始
    continue_text = FONT_MENU.render("按下鼠标左键继续......", True, FONT_COLOR)
    continue_text_rect = continue_text.get_rect(center=(W / 2, H / 2 + 100))
    SCREEN.blit(continue_text, continue_text_rect)

def draw_rank():
    SCREEN.fill((0, 0, 0))

    # 读取文件
    with open("./Data/rank.csv", "r") as f:
        reader = csv.reader(f)
        rank_list = list(reader)

    rank_list = rank_list[1:]
    # 排序
    rank_list.sort(key=lambda x: int(x[1]), reverse=True)

    #获取前四名
    rank_list = rank_list[:4]
    while True:
        # 绘制排行榜
        title = FONT_MENU.render("排行榜", True, FONT_COLOR)
        title_rect = title.get_rect(center=(W / 2, 100))
        SCREEN.blit(title, title_rect)

        for i in range(len(rank_list)):
            rank_text = FONT_SMALL.render(str(i + 1) + ". " + rank_list[i][0] + " " + rank_list[i][1], True, FONT_COLOR)
            rank_text_rect = rank_text.get_rect(center=(W / 2, i * 50 + 150))
            SCREEN.blit(rank_text, rank_text_rect)

        # 绘制返回按钮
        back_text = FONT_SMALL.render("返回", True, FONT_COLOR)
        back_text_rect = back_text.get_rect(center=(W / 2, H - 50))

        # 返回按钮的位置
        menu_pos.append(back_text_rect)
        mouse_pos = pygame.mouse.get_pos()
        if back_text_rect.collidepoint(*mouse_pos):
            back_text = FONT_SMALL.render("返回", True, HIGHT_COLOR)
        else:
            back_text = FONT_SMALL.render("返回", True, FONT_COLOR)
        SCREEN.blit(back_text, back_text_rect)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    if back_text_rect.collidepoint(*mouse_pos):
                        return

        pygame.display.update()
        CLOCK.tick(FPS)

# 判断鼠标点击的位置
def mouse_click_menu(mouse_pos):
    for menu in menu_pos:
        if menu.collidepoint(*mouse_pos):
            return menu_pos.index(menu)

def startGame():
    global food_pos,snake_body,score,food_pos_x,food_pos_x
    food_pos_x = random.randint(0, W // GRID_SIZE - 1) * GRID_SIZE
    foot_pos_y = random.randint(0, H // GRID_SIZE - 1) * GRID_SIZE
    food_pos = [food_pos_x, foot_pos_y]

    snake_body = [[SNAKE_START_POS[0], SNAKE_START_POS[1]]]
    score = 0
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    menu_index = mouse_click_menu(event.pos)
                    if menu_index == 0:
                        return
                    elif menu_index == 1:
                        draw_rank()
                    elif menu_index == 2:
                        pygame.quit()
                        sys.exit()
        mouse_pos = pygame.mouse.get_pos()
        draw_menu(mouse_pos)
        pygame.display.update()
        CLOCK.tick(FPS)


def runGame():
    global move_left, move_right, move_up, move_down, food_pos,score
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_LEFT and not move_right:
                move_left = True
                move_right = False
                move_up = False
                move_down = False
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT and not move_left:
                move_right = True
                move_left = False
                move_up = False
                move_down = False
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_UP and not move_down:
                move_up = True
                move_down = False
                move_right = False
                move_left = False
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_DOWN and not move_up:
                move_down = True
                move_up = False
                move_right = False
                move_left = False

        if move_right:
            snake_body.insert(0, [snake_body[0][0] + GRID_SIZE, snake_body[0][1]])
        if move_left:
            snake_body.insert(0, [snake_body[0][0] - GRID_SIZE, snake_body[0][1]])
        if move_up:
            snake_body.insert(0, [snake_body[0][0], snake_body[0][1] - GRID_SIZE])
        if move_down:
            snake_body.insert(0, [snake_body[0][0], snake_body[0][1] + GRID_SIZE])


        # 判断是否撞墙
        if snake_body[0][0] < 0 or snake_body[0][0] >= W or snake_body[0][1] < 0 or snake_body[0][1] >= H:
            return
        # 判断是否撞到自己
        for i in snake_body[1:]:
            if snake_body[0][0] == i[0] and snake_body[0][1] == i[1]:
                return

        #判断是否吃到食物
        if snake_body[0][0] == food_pos[0] and snake_body[0][1] == food_pos[1]:
            snake_body.append(snake_body[-1])
            food_pos_x = random.randint(0, W // GRID_SIZE-1) * GRID_SIZE
            foot_pos_y = random.randint(0, H // GRID_SIZE-1) * GRID_SIZE
            food_pos = [food_pos_x, foot_pos_y]
            score += 1

        draw_background_grid()
        snake_body.pop()

        # 绘制食物
        pygame.draw.rect(SCREEN, (123, 237, 159), (food_pos[0], food_pos[1], GRID_SIZE, GRID_SIZE))

        # 绘制分数
        score_text = FONT_MENU.render("分数：" + str(score), True, FONT_COLOR)
        score_text_rect = score_text.get_rect(center=(W / 2, 20))
        SCREEN.blit(score_text, score_text_rect)

        # 绘制蛇
        for i in snake_body:
            pygame.draw.rect(SCREEN, (255, 107, 129), (i[0], i[1], GRID_SIZE, GRID_SIZE))
        pygame.display.update()
        CLOCK.tick(FPS - 20)


def endGame():
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    return
        draw_end()
        pygame.display.update()
        CLOCK.tick(FPS)

def main():
    # 创建排行榜文件
    if not os.path.exists("./Data/rank.csv"):
        with open("./Data/rank.csv", "w") as f:
            f.write("date,score\n")
    while True:
        startGame()
        runGame()
        endGame()

        # 存储分数
        with open("./Data/rank.csv", "a") as f:
            f.write(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "," + str(score) + "\n")

if __name__ == '__main__':
    main()